package TrafficSim;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import TrafficSim.Master.augsburgSights;

@SuppressWarnings("serial")
public class TrafficRenderer extends JFrame {
	private boolean fullScreen=false;
	private boolean showMap = false;
	private Vector<Intersection> intersections;
	private JLayeredPane lp;
	private JLabel contentPanel;
	private ZoomAndPanListener z;
	private JLabel simTrafficGraph;
	private Simulation sim;
	private BufferStrategy bufferStrategy;
	private SimulationTrafficGraph simGraph;
	private Master m;
	private augsburgSights place;
	private GraphicsDevice graphicsDevice;
	boolean leaveMeAlone = false;
	private MapLayer map;
	protected int cars;
	private JLabel percentage;

	public TrafficRenderer(Vector<Intersection> graph, VehicleLists vehicleLists, Master m) {
		this.setJMenuBar(createMenuBar());
		this.m = m;
		this.setLayout(new BorderLayout());
		this.intersections = graph;
		this.sim = new Simulation(vehicleLists, intersections);
		this.contentPanel = sim;
		this.z = sim.getListener();
		simGraph = new SimulationTrafficGraph(
				intersections, z);
		this.simTrafficGraph = simGraph;
		this.map = new MapLayer(z);

		this.setTitle("TrafficSim");
		this.setSize(850, 850);
		this.lp = new JLayeredPane();
		this.lp.setBounds(1, 1, this.getWidth(), this.getHeight());
		this.add(lp, BorderLayout.CENTER);
		this.addComponentListener(new ComponentTestListener());
		this.addWindowListener(new ExitListener());
		if (showMap){
			this.lp.add(map, 1);
		}else{
			this.lp.add(simTrafficGraph, 1);
		}
		this.simTrafficGraph.setIgnoreRepaint(true);
		this.contentPanel.setOpaque(true);
		this.lp.add(contentPanel, 0);
		this.lp.getComponent(0).setBounds(1, -getJMenuBar().getHeight(), getWidth(),
				lp.getHeight());
		this.lp.getComponent(1).setBounds(1, -getJMenuBar().getHeight(), getWidth(),
				lp.getHeight());
//		this.lp.getComponent(2).setBounds(1, 1, this.getWidth(),
//				this.getHeight());
//		this.add(createEventLabel(),BorderLayout.SOUTH);
        this.graphicsDevice = getGraphicsConfiguration().getDevice();
        this.setVisible(true);
		this.createBufferStrategy(2);
		bufferStrategy = getBufferStrategy();
	}
	

    public void render() {	
		while(leaveMeAlone) {
    		try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
    	}
        Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
        this.paint(g);
        g.dispose();
        bufferStrategy.show();
    }

	private class ExitListener extends WindowAdapter {
		public void windowClosing(WindowEvent event) {
			System.exit(0);
		}
	}
	private JMenuBar createMenuBar(){
		JMenuBar menu = new JMenuBar();
		
		JMenu datei = new JMenu("Datei");
		
		menu.add(datei);
		JCheckBoxMenuItem pause = new JCheckBoxMenuItem("Pause");
		pause.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				m.pause();
			}
		});
		datei.add(pause);
		datei.addSeparator();
		JMenuItem beenden = new JMenuItem("Beenden");
		beenden.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);				
			}
		});
		datei.add(beenden);
		
		JMenu ansicht = new JMenu ("Ansicht");
		menu.add(ansicht);
		JCheckBoxMenuItem vollbild = new JCheckBoxMenuItem ("Vollbild");
		vollbild.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				leaveMeAlone = true;
				setFullscreen();
				leaveMeAlone = false;
			}
		});
		ansicht.add(vollbild);
//		group.add(vollbild);
		ansicht.addSeparator();
		
		ButtonGroup map = new ButtonGroup();
		JRadioButtonMenuItem showNetz = new JRadioButtonMenuItem ("Strassennetz");
		showNetz.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showMap = false;
				leaveMeAlone = true;
				toggleMap();
				leaveMeAlone = false;
			}
		});
		map.add(showNetz);
		ansicht.add(showNetz);
		showNetz.setSelected(true);
		JRadioButtonMenuItem showKarte = new JRadioButtonMenuItem ("Karte");
		showKarte.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showMap = true;
				leaveMeAlone = true;
				toggleMap();
				leaveMeAlone = false;
			}
		});
		map.add(showKarte);
		ansicht.add(showKarte);
		
		JMenu events = new JMenu ("Events");
		menu.add(events);
		JMenuItem startEvent = createEventLabel();
		events.add(startEvent);
//		startEvent.add(createEventLabel());
//		startEvent.addActionListener(new ActionListener() {
//			public void actionPerformed(ActionEvent arg0) {
//				createEventLabel();
//			}
//		});
//		JMenuItem loadEvent = new JMenuItem("Event laden");
//		events.add(loadEvent);
		
		JMenu help = new JMenu("Hilfe");
		menu.add(help);
		JMenuItem about = new JMenuItem("Dokumantation");
		help.add(about);
		JMenuItem stats = new JMenuItem("Auswertung ansehen");
		help.add(stats);
		
		
		return menu;
	}
	private void toggleMap(){
		this.lp.remove(lp.getComponent(1));
		this.z.changeSomething();
		if (showMap){
			this.lp.add(map, 1);
		}else{
			this.lp.add(simTrafficGraph, 1);
		}
		this.lp.getComponent(1).setBounds(1, -getJMenuBar().getHeight(), getWidth(),
				lp.getHeight());
	}
	private void setFullscreen(){
		if (fullScreen){
			this.dispose();
			this.setUndecorated(false);
			this.setResizable(true);
			GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
			GraphicsDevice gd = ge.getDefaultScreenDevice();
			gd.setFullScreenWindow(null);
			this.setVisible(true);
			this.fullScreen = false;
		}else{
			this.dispose();
			this.setUndecorated(true);
			this.setResizable(false);
	        this.setUndecorated(true);
	        graphicsDevice.setFullScreenWindow(this);
	        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 
	        graphicsDevice.setDisplayMode(new DisplayMode(dim.width, dim.height, 16, 60));
			this.fullScreen = true;
		}
	}
	private JPanel createCarPanel() {
//		JMenuItem percent = new JMenuItem();
//		percent.setBorder(new LineBorder(Color.gray));
//		percent.setLayout(new GridBagLayout());
//		GridBagConstraints g = new GridBagConstraints();
//		percent.setOpaque(true);
		JSlider s = new JSlider(JSlider.HORIZONTAL, 0, 5000, 0);
		JPanel sliderLabel = new JPanel();
		ChangeListener c = new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				JSlider source = (JSlider) e.getSource();

				TrafficRenderer.this.cars = source.getValue();
				String text = "<html>" + Integer.toString(TrafficRenderer.this.cars);
				TrafficRenderer.this.percentage.setText(text);
			}
		};
		String text = "<html>" + Integer.toString(TrafficRenderer.this.cars);
		this.percentage = new JLabel(text);

		s.setMajorTickSpacing(1000);
		s.setMinorTickSpacing(200);
		s.setPaintLabels(true);
		s.setPaintTicks(true);
		s.addChangeListener(c);
		
		
		sliderLabel.setLayout(new GridBagLayout());
		GridBagConstraints g = new GridBagConstraints();
		g.gridx = 0;
		g.gridy = 0;
		sliderLabel.add(new JLabel("Anzahl an Autos"), g);
		g.gridy = 1;
		sliderLabel.add(s, g);
		g.gridy = 2;
		sliderLabel.add(this.percentage,g);
		return sliderLabel;
	}
	private JMenuItem createEventLabel(){
		JMenu event = new JMenu("Event starten");
		event.setLayout(new GridBagLayout());
		final JTextField cars = new JTextField(4);
		JButton start = new JButton("Start Event");

		
		augsburgSights[] sa = augsburgSights.values();
		GridBagConstraints g = new GridBagConstraints();
		g.anchor = GridBagConstraints.WEST;
		g.gridx = 1;
		g.gridy = 0;
		event.add(createCarPanel());
		g.gridx = 0;
		for (augsburgSights a: sa){
			JMenuItem rb = new JMenuItem(a.toString());
			event.add(rb);
			rb.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					if (e.getActionCommand() == "FH"){place = augsburgSights.FH;}
					if (e.getActionCommand() == "CITYGALERIE"){place = augsburgSights.CITYGALERIE;}
					if (e.getActionCommand() == "KOENIGSPLATZ"){place = augsburgSights.KOENIGSPLATZ;}
					if (e.getActionCommand() == "MAN"){place = augsburgSights.MAN;}
					if (e.getActionCommand() == "MAXSTRASSE"){place = augsburgSights.MAXSTRASSE;}
					if (e.getActionCommand() == "PLAERRER"){place = augsburgSights.PLAERRER;}
					if (e.getActionCommand() == "SCHWABENCENTER"){place = augsburgSights.SCHWABENCENTER;}
					if (e.getActionCommand() == "RANDOM"){place = augsburgSights.RANDOM;}					
				
				try{
					int numberOfCars = TrafficRenderer.this.cars;
					m.startEvent(place, numberOfCars);
					}catch (NumberFormatException ex){
						return;
					}
			}});
			g.gridy++;
		}
		start.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				try{
				int numberOfCars = Integer.parseInt(cars.getText());
				m.startEvent(place, numberOfCars);
				}catch (NumberFormatException ex){
					return;
				}
			}
		});
		g.gridx = 1;
		g.gridy = 0;
		g.gridheight = 7;
//		event.add(start);
//		popup.add(event);
//		popup.pack();
//		popup.show(null, 100, 100);
		return event;
		}

	private class ComponentTestListener extends ComponentAdapter {
		public void componentResized(ComponentEvent e) {
			TrafficRenderer source = (TrafficRenderer) e.getSource();
			source.z.changeSomething();
			source.lp.getComponent(0).setBounds(1, -getJMenuBar().getHeight(), source.getWidth(),
					source.lp.getHeight());
			source.lp.getComponent(1).setBounds(1, -getJMenuBar().getHeight(), source.getWidth(),
					source.lp.getHeight());
		}
	}
}
